<!--- 
OutlookCalendar CFC

COPYRIGHT & LICENSING INFO
-------------------------------------------------------------------

Copyright 2006 TJ Downes - tdownes@sanative.net - http://www.sanative.net

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
--->
<cfcomponent displayName="OutlookCalendar" hint="A Outlook Calendar processor." output="false">

	<cfset variables.data = "">
	
	<cffunction name="init"
			returnType="OutlookCalendar"
			access="public"
			output="false"
			hint="Init function for the CFC. Loads in the initial string data.">
	
		<cfargument name="data"
				type="string"
				required="true">
		
		<cfset variables.data = arguments.data>
		
		<cfreturn this>
		
	</cffunction>
	
	<cffunction name="getEvents"
			returnType="array"
			access="public"
			output="false"
			hint="Gets the events from an Outlook Calendar CSV.">

		<cfscript>
			var results = ParseOfficeCSV(variables.data);
			var ImportData = ArrayNew(1);
			var ArrayCount = 0;
		</cfscript>
		
		<cfloop from="1" to="#ArrayLen(results)#" index="x">
			<cfif Compare(results[x].Subject, ",")>
			<cfif Len(Trim(results[x]["Start Date"]))>
				<cfset ArrayCount = ArrayCount + 1 />
				<cfscript>
					ImportData[ArrayCount] = StructNew();
					ImportData[ArrayCount].Title = Left(results[x].Subject, 150);
					ImportData[ArrayCount].StartDate = results[x]["Start Date"];
					if(Len(Trim(results[x]["End Date"]))) {
						ImportData[ArrayCount].EndDate = results[x]["End Date"];
					} else {
						ImportData[ArrayCount].EndDate = results[x]["Start Date"];
					}
					ImportData[ArrayCount].StartTime = results[x]["Start Time"];
					ImportData[ArrayCount].EndTime = results[x]["End Time"];
					if(StructKeyExists(results[x], "Description")) {
						ImportData[ArrayCount].Description = results[x].Description;
					} else {
						ImportData[ArrayCount].Description = "Description unavailable";
					}
				</cfscript>
			</cfif>
			</cfif>
		</cfloop>
		
		<cfreturn ImportData />

	</cffunction>
	
	<cffunction name="ParseOfficeCSV"
			returnType="array"
			access="private"
			output="false"
			hint="Parses an MS Office CSV.">
		
		<cfargument name="data" type="string" required="true" />
		<!--- Adapted from ParseOfficeCSV developed by:
		AUTHOR:	Tariq Ahmed. tariq@dopejam.com. http://www.dopejam.com
		If you use this code for anything else please give Tariq credit! ---> 
		<cfscript>
		 	var theFile = data;
			var ImportArray = ArrayNew(1);
			var TitleArray = ArrayNew(1);
			var ArrayCounter = 0;
			var EOL = 0;
			var Last = 1;
			var	ColStart = 1;
			var	ColEnd = 0;
			var	ColCounter = 0;
			var FoundIt = 0;
			var aColumn = 0;
			var col = "";
			var aLine = "";
			var val = "";
		</cfscript>
		<cfloop Condition="EOL LT Len(theFile)">
    		<cfset EOL = FindNoCase("""#chr(13)#",theFile,Last) />
    		<cfif NOT EOL>
	   			<cfset EOL = Len(theFile) + 1 />
	   		<cfelse>
				<cfset ArrayCounter = ArrayCounter + 1 />
				<cfif ArrayCounter neq 1>
					<cfset ImportArray[ArrayCounter-1] = StructNew() />
				</cfif>
				<!--- clean up the line --->
				<cfscript>
					aLine = trim(Mid(theFile,Last,EOL - Last + 1));
					aLine = replaceNoCase(aLine,chr(13),"","ALL");
					aLine = replaceNoCase(aLine,chr(10),"","ALL");
					ColStart = 1;
					ColEnd = 0;
					ColCounter = 0;
				</cfscript>
				<cfloop Condition="COLSTART LT Len(aline)">
				<cfset ColCounter = ColCounter + 1 />
				<!--- find when the current column ends assuming this pattern "info",,,,,"info",etc... --->
				<!--- we've found when it ends when we find a , that has either a " or another , before it --->
				<cfset Foundit = 0 />
				<cfset ColEnd = ColStart />
				<cfloop Condition="NOT FoundIt">
					<cfset ColEnd = FindNoCase(",",aline,ColEnd) />
					<cfif NOT ColEnd>
						<cfset FoundIt = 1 />
					<cfelse>
						<cfif ColEnd gt 1>
							<cfif Mid(aLine,ColEnd - 1,1) eq "," OR Mid(aLine,ColEnd - 1,1) eq """">
								<cfset FoundIt = 1 />
							<cfelse>
								<cfset ColEnd = ColEnd + 1 />
							</cfif>
						<cfelse>
							<cfset FoundIt = 1 />
						</cfif>
					</cfif>
				</cfloop>
				<cfif NOT COLEND>
					<!--- this is the last bit, the last column will just end with a quote... --->
					<cfset aColumn = Mid(aLine,ColStart + 1,Len(aline)-ColStart + 1) />
					<cfset aColumn = ReplaceNoCase(aColumn,"""","","ALL") />
					<cfset ColStart = Len(aline) + 1 />
				<cfelse>
					<cfset aColumn = Mid(aLine,ColStart + 1,ColEnd-ColStart) />
					<cfset ColStart = ColEnd + 1 />
					<cfset aColumn = ReplaceNoCase(aColumn,""",","","ALL") />
				</cfif>
				<cfif ArrayCounter eq 1>
					<!--- we're on the first row, we're assuming this is the title row --->
					<cfset TitleArray[ColCounter] = aColumn>
				<cfelse>
					<cfset val=StructInsert(ImportArray[ArrayCounter-1], TitleArray[ColCounter], aColumn)>
				</cfif>
			</cfloop>
			<cfset Last = EOL + 1 />
		</cfif>
	</cfloop>
	
	<cfreturn ImportArray>
	
	</cffunction>

</cfcomponent>